package za.org.meraka.cair.ontorepair;

import org.semanticweb.owlapi.model.*;
//import uk.ac.manchester.syntactic_locality.*;
import uk.ac.manchester.cs.owlapi.modularity.*;

import java.util.HashSet;
import java.util.Set;

public class ModuleExtractor{	  
    //private ModuleExtractorManager moduleManager;
    public Set<OWLAxiom> disjointAxioms;	
    public Set<OWLAxiom> subClassAxioms;
    public Set<OWLAxiom> eqClassAxioms;
    public Set<OWLAxiom> otherAxioms;
    public Set<OWLAxiom> startSet;
    private UtilityClass<OWLEntity> u;
    private boolean b;
    private SyntacticLocalityModuleExtractor moduleExtractor;
    
	public ModuleExtractor(){
		u = new UtilityClass<OWLEntity>();		
		b = true;
	}	
	
	public OWLOntology extractModule(OWLOntology o, OWLOntologyManager man, Signature s) throws OWLException{		
		moduleExtractor = new SyntacticLocalityModuleExtractor(man, o, ModuleType.STAR);
		IRI iri = IRI.create(o.getOntologyID().toString());//"http://www.co-ode.org/ontologies/pizza/pizza.owl");
		OWLOntology result = moduleExtractor.extractAsOntology(s.elements, iri);
		
		/*moduleManager = new ModuleExtractorManager(o, "UM", true, false);
		OWLOntology result = moduleManager.extractModule(new HashSet<OWLEntity>(s.elements));*/
		return result;
	}
	
	public void processAxioms(OWLOntology o) throws OWLException{
		Set<OWLAxiom> allAxioms = new HashSet<OWLAxiom>(o.getAxioms());
		startSet = new HashSet<OWLAxiom>();
		int i = o.getAxiomCount()/10;
		//int i = 10;
		for (OWLAxiom tmp: o.getAxioms()){
			if (i > 0){
				startSet.add(tmp);
				allAxioms.remove(tmp);
			}
			i--;
		}
		
		disjointAxioms = new HashSet<OWLAxiom>();
		subClassAxioms = new HashSet<OWLAxiom>();
		eqClassAxioms = new HashSet<OWLAxiom>();
		otherAxioms = new HashSet<OWLAxiom>();
		for (OWLAxiom tmp: allAxioms){
			if (tmp.getAxiomType().equals(AxiomType.DISJOINT_CLASSES)){
				disjointAxioms.add(tmp);
			}
			else if (tmp.getAxiomType().equals(AxiomType.SUBCLASS_OF)){
				subClassAxioms.add(tmp);
			}
			else if (tmp.getAxiomType().equals(AxiomType.EQUIVALENT_CLASSES)){
				eqClassAxioms.add(tmp);
			} 
			else{
				otherAxioms.add(tmp);
			}
		}
	}
	
	private Set<OWLAxiom> getDefiningAxioms(Signature s){
		Set<OWLAxiom> result = new HashSet<OWLAxiom>();
		for (OWLEntity e: s.elements){
			for (OWLAxiom sTmp: subClassAxioms){
				if (b)
				System.out.println(sTmp);
				OWLSubClassOfAxiom sub = (OWLSubClassOfAxiom)sTmp;
				if (e.toString().equals(sub.getSubClass().toString()))
					result.add(sTmp);
			}
			for (OWLAxiom eTmp: eqClassAxioms){				
				if (eTmp.getSignature().contains(e))
					result.add(eTmp);
			}
			for (OWLAxiom oTmp: otherAxioms){				
				if (oTmp.getSignature().contains(e))
					result.add(oTmp);
			}
			for (OWLAxiom dTmp: disjointAxioms){
				if (b)
				System.out.println(dTmp);
				if (dTmp.getSignature().contains(e))
					result.add(dTmp);
			}						
		}
		b = false;
		return result;
	}
	
	public Set<OWLAxiom> selectSubSet(Signature s) throws OWLException{
		Set<OWLAxiom> result = new HashSet<OWLAxiom>();
		if (s.elements.size() == 0){
			result.addAll(startSet);
			System.out.println("Start size: " + startSet.size());
		}
		else{
			//Defining axioms for each entity in s.
			Set<OWLAxiom> tmp = new HashSet<OWLAxiom>(getDefiningAxioms(s));
			System.out.println(tmp.size());
			result.addAll(tmp);
			
		}
		return result;
	}
	
	private Set<OWLAxiom> directRelevance(OWLOntology o, Signature s){
		Set<OWLAxiom> result = new HashSet<OWLAxiom>();
		for (OWLAxiom tmp: o.getAxioms()){
			if (!(u.intersection(tmp.getSignature(), s.elements).isEmpty())){
				result.add(tmp);
			}
		}
		return result;
	}
	
	private Set<OWLAxiom> directRelevance(OWLOntology o, Set<OWLAxiom> set){
		Set<OWLAxiom> result = new HashSet<OWLAxiom>();
		for (OWLAxiom tmp: o.getAxioms()){
			for (OWLAxiom setTmp: set){
				if (!(u.intersection(tmp.getSignature(), setTmp.getSignature()).isEmpty())){
					result.add(tmp);
				}
			}						
		}
		
		return result;
	}
	
	public Set<OWLAxiom> selectionFunction(OWLOntology o, Signature s, int k) throws OWLException{		
		Set<OWLAxiom> result = new HashSet<OWLAxiom>();
		if (k >= 1){
			if (k == 1){
				result = new HashSet<OWLAxiom>(directRelevance(o,s));
			}
			else if (k > 1){
				if (k == 2){
					result = new HashSet<OWLAxiom>(directRelevance(o, selectionFunction(o,s,1)));					
				}
				else{
					result = new HashSet<OWLAxiom>(directRelevance(o, selectionFunction(o,s,k-1)));
				}
			}
		}		
		return result;
	}
}
